package com.ikun.admin.modules.sys.tool.excel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ikun.admin.modules.sys.entity.User;
import com.ikun.admin.modules.sys.service.UserService;
import com.ikun.admin.modules.sys.vo.UserExportAndImportVo;
import com.ikun.common.exception.MyException;
import com.ikun.common.utils.DataCopy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.*;

/**
 * @ClassName UserExcelListener
 * @Description:
 * @CreateDate: 2024/8/6 11:15
 */
@Slf4j
public class UserExcelListener implements ReadListener<UserExportAndImportVo> {

    /**
     * 每次储存的数据条数100条
     */
    private static final int BATCH_COUNT = 100;

    private static final String DEFAULT_PASSWORD = "ikun666";
    /**
     * 缓存的数据
     */
    private List<UserExportAndImportVo> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
     * 操作数据库 通过构造函数传入 不能纳入spring管理
     */
    private UserService userService;

    //加密器也要传进来 对密码进行加密
    private PasswordEncoder passwordEncoder;


    public UserExcelListener(UserService userService, PasswordEncoder passwordEncoder) {
        this.userService = userService;
        this.passwordEncoder = passwordEncoder;
    }


    /**
     * 解析出来的数据
     * @param userExportAndImportVo
     * @param analysisContext
     */
    @Override
    public void invoke(UserExportAndImportVo userExportAndImportVo, AnalysisContext analysisContext) {
        log.info("解析出一条用户数据:{}", userExportAndImportVo);
        cachedDataList.add(userExportAndImportVo);
        if (cachedDataList.size() >= BATCH_COUNT) {
            this.saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        this.saveData();
        log.info("所有用户数据解析完成！");
    }

    private void saveData() {
        log.info("{}条数据，开始存储数据库！", cachedDataList.size());
        //数据处理
        List<User> userList = DataCopy.copyToListObj(cachedDataList, User.class);
        Set<String> errorMobileSet = new HashSet<>();
        Set<String> errorEmailSet = new HashSet<>();
        List<String> mobileSet = new ArrayList<>();
        List<String> emailSet = new ArrayList<>();
        userList.forEach(user -> {
            if (Objects.isNull(user.getMobile()) || !user.getMobile().matches("^1[3-9]\\d{9}$")) {
                errorMobileSet.add(user.getMobile());
            } else {
                mobileSet.add(user.getMobile());
            }
            if (Objects.isNull(user.getEmail()) || !user.getEmail().matches("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$")) {
                errorEmailSet.add(user.getEmail());

            } else {
                emailSet.add(user.getEmail());
            }
        });
        List<User> existUserList = new ArrayList<>();
        if (mobileSet.size() > 0 || existUserList.size() > 0) {
            existUserList = userService.list(new QueryWrapper<User>().lambda().in(mobileSet.size() > 0, User::getMobile, mobileSet).in(emailSet.size() > 0, User::getEmail, emailSet));
        }
        List<User> normalUseList = new ArrayList<>();
        if (existUserList.size() > 0) {
            existUserList.forEach(user -> userList.stream().forEach(item -> {
                if (Objects.equals(item.getMobile(), user.getEmail())) {
                    errorMobileSet.add(item.getMobile());
                }
                if (Objects.equals(item.getEmail(), user.getEmail())) {
                    errorEmailSet.add(item.getEmail());
                }
                if (!errorMobileSet.contains(item.getMobile()) && !errorEmailSet.contains(item.getEmail())) {
                    normalUseList.add(item);
                }
            }));
        }
        //保存数据
        if (normalUseList.size() > 0) {
            normalUseList.forEach(item->{
                item.setUsername(item.getMobile());
                item.setPassword(passwordEncoder.encode(DEFAULT_PASSWORD));
            });
            userService.saveBatch(normalUseList);
        }
        if (errorMobileSet.size() > 0 || errorEmailSet.size() > 0) {
            throw new MyException(this.buildErrorMessage(errorMobileSet, errorEmailSet));
        }

    }

    private String buildErrorMessage(Set<String> mobileSet, Set<String> eamilSet) {

        StringBuilder msg = new StringBuilder();
        msg.append("导入部分失败:");
        if (mobileSet.size() > 0) {
            msg.append("下列手机号格式不对或者已存在:");

            mobileSet.forEach(item -> msg.append(item).append(","));

        }
        if (eamilSet.size() > 0) {
            msg.append("下列邮箱格式不对或者已存在:");
            eamilSet.forEach(item -> msg.append(item).append(","));
        }
        return msg.toString();
    }
}
